#define _WIN32_WINNT 0x0501			//for windows XP or higher, since it depends on Raw Input APIs
#include<windows.h>
#include<atlbase.h>
#include <atlwin.h>
#include <string>
#include <sstream>
using namespace std;

#define LIB extern "C" __declspec(dllexport)

#pragma region shared
#pragma data_seg("MIshare")
HWND s_hwndMaster = NULL;
#pragma data_seg()
#pragma comment(linker, "/section:MIshare,rws")
#pragma endregion shared

#define WM_INJECTED_INPUT_FIRST	(WM_APP + WM_KEYFIRST)
#define WM_INJECTED_INPUT_LAST	(WM_APP + WM_KEYLAST)
HINSTANCE g_hinstDll=NULL;

BOOL WINAPI DllMain(HINSTANCE hinstDll, DWORD fdwReason, PVOID fImpLoad) {

	switch (fdwReason) {

	  case DLL_PROCESS_ATTACH:
		  // DLL is attaching to the address space of the current process.
		  g_hinstDll = hinstDll;
		  break;

	  case DLL_THREAD_ATTACH:
		  // A new thread is being created in the current process.
		  break;

	  case DLL_THREAD_DETACH:
		  // A thread is exiting cleanly.
		  break;

	  case DLL_PROCESS_DETACH:
		  // The calling process is detaching the DLL from its address space.
		  break;
	}
	return(TRUE);
}

bool isVisualStudio(HWND hwnd)
{
	if(hwnd)
	{
		CWindow win(hwnd);
		TCHAR arr[100];
		win = win.GetTopLevelParent();
		win.GetWindowText(arr,100);
		wstring str(arr);
		return (str.find(TEXT("Visual Studio")) < str.size());
	}
	return false;
}
wstringstream sout;
LIB LRESULT CALLBACK GetMsgProc(int nCode,WPARAM wParam,LPARAM lParam)
{
	LPMSG pmsg = (LPMSG)lParam;
	
	if(nCode >= 0 && pmsg->hwnd != s_hwndMaster && !isVisualStudio(pmsg->hwnd))
	{
		sout<<hex;
		if(pmsg->message >= WM_KEYFIRST && pmsg->message <= WM_KEYLAST && pmsg->message != WM_CHAR) //if not a System keybouard message
		{
			sout << pmsg->message <<"  -OOcode:"<<pmsg->wParam<<" -  "<<pmsg->lParam<<"\r\n";
			pmsg->message = WM_NULL;									//replace it
		}

		if(pmsg->message == WM_CHAR )
		{
			sout << pmsg->message <<"  -CCcode:"<<pmsg->wParam<<"\r\n";
			//if(pmsg->wParam == 'p')
			//	MessageBox(0,sout.str().c_str(),0,0);
		}	
		if(pmsg->message >= WM_INJECTED_INPUT_FIRST && pmsg->message <= WM_INJECTED_INPUT_LAST)
		{
			pmsg->message =pmsg->message - WM_APP;

  			sout << pmsg->message <<"  -SScode:"<<pmsg->wParam<<" -  "<<pmsg->lParam<<"\r\n";
		}
		
		
	}
	return CallNextHookEx(NULL,nCode, wParam, lParam);
}


LIB LRESULT CALLBACK CBTProc(int nCode, WPARAM wParam,LPARAM lParam)
{
	if(nCode >= 0)
	{
		
	}
	return CallNextHookEx(NULL,nCode, wParam, lParam);
}


LIB LRESULT CALLBACK KeyboardProc(int nCode,WPARAM wParam,LPARAM lParam)
{
	if(nCode >= 0)
	{
		return 1;
	}
	return CallNextHookEx(NULL,nCode, wParam, lParam);
}

LIB void SetMasterWindow(HWND hwnd)
{
	s_hwndMaster = hwnd;
}
